<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Select</title>

<style>
.xc-select {
    position: relative;
    display: inline-block;
    background-color: #fff;
    height: 30px;
    line-height: 30px;
    font-size: 14px;
    color: rgba(0, 0, 0, .6);
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    transition: border-color .5s;
}
.xc-select:after {
    content: '▼';
    position: absolute;
    top: 0;
    right: 6px;
}
.xc-select:focus,
.xc-select:hover {
    border-color: #49a9ee
}
.xc-select-text {
    display: inline-block;
    padding-left: 10px;
}
.xc-select-list {
    position: absolute;
    z-index: 600;
    left: 0;
    top: 31px;
    width: 100%;
    max-height: 300px;
    padding: 10px 0;
    background-color: #fff;
    overflow-y: auto;
    box-shadow: 0 4px 6px 0 rgba(0, 0, 0, .2);
    display: none;
}
.xc-select-list span {
    display: block;
    height: 32px;
    line-height: 32px;
    padding: 0 6px;
}
.xc-select-list span:hover {
    background-color: #eee;
    cursor: pointer;
}
</style>
<script>
function Select() {
    this.doc = document;
    this.wrapper = null;
    this.textWrapper = null;
    this.listWrapper = null;
    this.onChange = null;

    this.value = '';
}
Select.prototype = {
    constructor: Select,
    E: {
        addHandler: function(ele, type, func) {
            if(ele.addEventListener) {
                ele.addEventListener(type, func, false);

            } else if(ele.attachEvent) {
                ele.attachEvent('on' + type, func);

            } else {
                ele['on' + type] = func;
            }
        },
        removeHandler: function(ele, type, func) {
            if(ele.removeEventListener) {
                ele.removeEventListener(type, func, false);

            } else if(ele.detachEvent) {
                ele.detachEvent('on' + type, func);

            } else {
                ele['on' + type] = null;
            }
        }
    },
    closeList: function() {
        this.listWrapper.style.display = 'none';
    },
    eventHandler: function(e) {
        e.stopPropagation && e.stopPropagation();
        e.cancelBubble = true;

        var target = e.target;

        if('block' !== this.listWrapper.style.display) {
            this.listWrapper.style.display = 'block';

        } else {
            this.listWrapper.style.display = 'none';
        }

        if('item' === target.getAttribute('data-role')) {
            this.value = target.getAttribute('data-value');
            this.textWrapper.innerHTML = target.innerHTML;

            if(null !== this.onChange) {
                this.onChange(this.value);
            }
        }
    },
    initStructure: function(items) {
        this.wrapper.className += ' xc-select';
        this.textWrapper = this.doc.createElement('span');
        this.textWrapper.className = 'xc-select-text';
        this.listWrapper = this.doc.createElement('div');
        this.listWrapper.className = 'xc-select-list';

        var ret = '';
        for(var i=0,len=items.length; i<len; i++) {
            ret += '<span data-role="item" data-value="'+ items[i].value +'">'+ items[i].text +'</span>';
        }
        this.listWrapper.innerHTML = ret;

        this.wrapper.appendChild(this.textWrapper);
        this.wrapper.appendChild(this.listWrapper);
    },
    processDefaultValue: function(value) {
        var list = this.listWrapper.querySelectorAll('[data-role="item"]');

        // 匹配不到 则不设置值
        for(var i=0,len=list.length; i<len; i++) {
            if(value === list[i].getAttribute('data-value')) {
                this.value = value;
                this.textWrapper.innerHTML = list[i].innerHTML;

                break;
            }
        }

        if(null !== this.onChange) {
            this.onChange(value);
        }
    },

    /**
     * 渲染
     *
     * @param Element wrapper
     * @param Array items eg. [ {text: '选项描述', value: '1'} ]
     */
    render: function(wrapper, items) {
        var _self = this;
        var select = this.wrapper = wrapper;

        this.initStructure(items);

        select.onclick = function(e) {
            _self.eventHandler(e);
        };
        select = null;

        this.E.addHandler(this.doc, 'click', function(e){
            _self.closeList();
        });

        return this;
    },
    getValue: function() {
        return this.value;
    },
    setValue: function(value) {
        this.processDefaultValue(String(value));
    }
};
</script>
</head>
<body>

<div id="demo" style="width: 120px"></div>

<script>
var se = new Select();
se.render(document.getElementById('demo'), [
    {text: 'this is one', value: '1'},
    {text: '这是第二', value: '2'},
    {text: '这是第三个', value: '3'},
]);
se.onChange = (v) => {
    console.log(v);
};

setTimeout(() => {
    se.setValue('1');
}, 1000);
</script>
</body>
</html>
